"""
邮件运送库
- background在 Session 由于共享问题 DBConnect().sessionLocal()已使用
"""
import smtplib
from datetime import datetime
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr

from fastapi import Request
from fastapi.templating import Jinja2Templates

from core.database import DBConnect
from core.models import Config, Member, PollEtc, QaConfig, QaContent
from core.settings import settings
from core.template import TemplateService
from lib.common import cut_name, get_admin_email, get_admin_email_name

_SMTP_SERVER = settings.SMTP_SERVER
_SMTP_PORT = settings.SMTP_PORT
_SMTP_USERNAME = settings.SMTP_USERNAME
_SMTP_PASSWORD = settings.SMTP_PASSWORD


def mailer(from_email: str, to_email: str, subject: str, body: str,
           from_name: str = None, to_name: str = None) -> None:
    """邮件发送功能

    Args:
        from_email (str): 发送人电子邮件
        email (str): 到电子邮件 (,可以发送给多个人，由)
        subject (str): 标题
        body (str): 内容
        from_name (str, optional): 发送人员姓名. Defaults to None.
        to_name (str, optional): 要的人的姓名. Defaults to None.

    Raises:
        SMTPAuthenticationError: SMTP 当身份验证信息有误时
        SMTPServerDisconnected: SMTP 无法连接到服务器或断开连接时
        SMTPException: 发送邮件时出现错误
        Exception: 其他错误
    """
    try:
        # Daum, Naver 邮件是 SMTP_SSL我使用.
        if _SMTP_PORT == 465:
            server = smtplib.SMTP_SSL(_SMTP_SERVER, _SMTP_PORT, timeout=10)
        else: # port: 587
            server = smtplib.SMTP(_SMTP_SERVER, _SMTP_PORT, timeout=10)
            server.starttls()

        if _SMTP_USERNAME and _SMTP_PASSWORD:
            server.login(_SMTP_USERNAME, _SMTP_PASSWORD)

        msg = MIMEMultipart()
        msg['From'] = formataddr((str(Header(from_name, 'utf-8')), from_email))
        msg['To'] = formataddr((str(Header(to_name, 'utf-8')), to_email))
        msg['Subject'] = subject
        # Assuming body is HTML, if not change 'html' to 'plain'
        msg.attach(MIMEText(body, 'html'))

        server.sendmail(from_email, to_email, msg.as_string())

    except smtplib.SMTPAuthenticationError as e:
        print(f"SMTP 身份验证信息不正确. {e}")
    except smtplib.SMTPServerDisconnected as e:
        print(f"SMTP 无法连接到服务器或断开连接. {e}")
    except smtplib.SMTPException as e:
        print(f"发送邮件时出错. {e}")
    except Exception as e:
        print(e)
    finally:
        try:
            server.quit()
        except Exception as e:
            pass


async def send_password_reset_mail(request: Request, member: Member) -> None:
    """background task > 邮件发送密码重置链接

    Args:
        request (Request): Request 对象
        member (Member): 新成员
    """
    with DBConnect().sessionLocal() as db:
        request.state.config = config = db.query(Config).first()

    try:
        templates = Jinja2Templates(
            directory=TemplateService.get_templates_dir())

        subject = f"[{config.cf_title}] 找到您的密码邮件。."
        body = templates.TemplateResponse(
            "bbs/mail_form/find_pasword_mail.html",
            {
                "request": request,
                "member": member,
                "datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            }
        ).body.decode("utf-8")
        mailer(get_admin_email(request), member.mb_email,
               subject, body, get_admin_email_name(request))
    except Exception as e:
        print(e)


async def send_register_mail(request: Request, member: Member) -> None:
    """background task > 会员的邮件发送处理

    Args:
        request (Request): Request 对象
        member (Member): 新成员
    """
    with DBConnect().sessionLocal() as db:
        request.state.config = config = db.query(Config).first()

    try:
        templates = Jinja2Templates(directory=TemplateService.get_templates_dir())
        from_email = get_admin_email(request)
        from_name = get_admin_email_name(request)
        context = {"request": request, "member": member}
        # 发送身份验证邮件
        if config.cf_use_email_certify:
            subject = f"[{config.cf_title}] 关于会员资格验证的邮件"
            context.update(
                {"certify_href": f"{str(request.base_url)}bbs/email_certify/{member.mb_id}?certify={member.mb_email_certify2}"}
            )
            body = templates.TemplateResponse(
                "bbs/mail_form/register_certify_mail.html",
                context
            ).body.decode("utf-8")
        # 邮件会员
        elif config.cf_email_mb_member:
            subject = f"[{config.cf_title}] 祝贺您成为会员."
            body = templates.TemplateResponse(
                "bbs/mail_form/register_send_member_mail.html",
                context
            ).body.decode("utf-8")
        mailer(from_email, member.mb_email, subject, body, from_name)
    except Exception as e:
        print(e)


async def send_register_admin_mail(request: Request, member: Member) -> None:
    """background task > 处理向最高管理者发送会员电子邮件

    Args:
        request (Request): Request 对象
        member (Member): 新成员
    """
    with DBConnect().sessionLocal() as db:
        request.state.config = config = db.query(Config).first()

    try:
        templates = Jinja2Templates(
            directory=TemplateService.get_templates_dir())
        from_email = get_admin_email(request)
        from_name = get_admin_email_name(request)
        context = {"request": request, "member": member}

        if config.cf_email_mb_super_admin:
            subject = f"[{config.cf_title}] {member.mb_nick} 你是会员。."
            body = templates.TemplateResponse(
                "bbs/mail_form/register_send_admin_mail.html",
                context
            ).body.decode("utf-8")
            mailer(from_email, config.cf_admin_email, subject, body, from_name)
    except Exception as e:
        print(e)


async def send_poll_etc_mail(request: Request, poll_etc: PollEtc) -> None:
    """
    处理向高层管理人员发送其他意见邮件
    - 基本环境设置 > 仅当您有其他评论邮件设置时发送

    Args:
        request (Request): Request 对象
        poll_etc (PollEtc): 其他意见蒙昧
    """
    with DBConnect().sessionLocal() as db:
        request.state.config = config = db.query(Config).first()

    try:
        if config.cf_email_po_super_admin and config.cf_admin_email:
            templates = Jinja2Templates(
                directory=TemplateService.get_templates_dir())
            email = get_admin_email(request)
            from_name = get_admin_email_name(request)
            subject = f"[{config.cf_title}] 调查 - 其他意见邮件"
            body = templates.TemplateResponse(
                "bbs/mail_form/poll_etc_update_mail.html",
                {
                    "request": request,
                    "subject": subject,
                    "mb_name": cut_name(request, poll_etc.pc_name),
                    "mb_id": poll_etc.mb_id if poll_etc.mb_id else "非会员",
                    "content": poll_etc.pc_idea,
                }
            ).body.decode("utf-8")
            mailer(email, email, subject, body, from_name)
    except Exception as e:
        print(e)


async def send_qa_mail(request: Request, qa: QaContent) -> None:
    """
    Q&A 注册时的邮件发送处理
    - Q&A 在注册时, 邮件到设置中注册的管理员电子邮件地址
    - 注册时的答案, 邮件/根据接收或不设置将邮件发送给用户
    - 답변글 등록 시, 메일/메일 수신여부 설정에 따라 사용자에게 메일 발송
    
    Args:
        request (Request): Request 对象
        poll_etc (PollEtc): 其他意见蒙昧
    """
    with DBConnect().sessionLocal() as db:
        request.state.config = config = db.query(Config).first()
        qa_config = db.query(QaConfig).first()

    from_email = get_admin_email(request)
    from_name = get_admin_email_name(request)
    subject = f"[{config.cf_title}] {qa_config.qa_title} 问题通知邮件"
    content = qa.qa_subject + "<br><br>" + qa.qa_content
    templates = Jinja2Templates(
                directory=TemplateService.get_templates_dir())

    if qa.qa_parent:
        question = db.get(QaContent, qa.qa_parent)
        if question.qa_email_recv and question.qa_email:
            subject = f"{subject} 的答案已注册."
            content = templates.TemplateResponse(
                "bbs/mail_form/qa_answered_mail.html", {
                    "request": request,
                    "qa_subject": qa.qa_subject,
                    "qa_name": qa.qa_name,
                    "qa_content": qa.qa_content,
                    "link_url": request.url_for("qa_view", qa_id=qa.qa_parent),
                }
            ).body.decode("utf-8")
            mailer(from_email, question.qa_email, subject, content, from_name)
    else:
        if qa_config.qa_admin_email:
            content = templates.TemplateResponse(
                "bbs/mail_form/qa_answered_mail.html", {
                    "request": request,
                    "qa_subject": qa.qa_subject,
                    "qa_name": qa.qa_name,
                    "qa_content": qa.qa_content,
                    "link_url": request.url_for("qa_view", qa_id=qa.qa_id),
                }
            ).body.decode("utf-8")
            mailer(from_email, qa_config.qa_admin_email, subject, content, from_name)
